package com.sun.gis.tools.photo;

import org.geotools.data.DataUtilities;
import org.geotools.data.FeatureSource;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.*;
import org.geotools.styling.Stroke;
import org.geotools.swing.JMapFrame;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.FilterFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 基于shapefile文件生成全局四至图
 */
public class TestScreenshot1 {

    public static void main(String[] args) throws IOException {
        // 加载Shapefile文件
        File shapefile = new File("D:\\data\\output\\photo\\demo\\demo.shp");
        ShapefileDataStore dataStore = new ShapefileDataStore(shapefile.toURI().toURL());
        SimpleFeatureSource featureSource = dataStore.getFeatureSource();
        // 为shapefile的特征创建样式
//        Style style = SLD.createSimpleStyle(featureSource.getSchema());
        Style style = createCustomStyle();
        Layer layer = new FeatureLayer(featureSource, style);

        String outputPath = "D:\\data\\output\\photo\\map_view1.png";
        getFourScreenshots(layer, outputPath);
    }


    private void test() throws IOException {
        // 加载Shapefile文件
        File shapefile = new File("E:\\data\\GIS\\division\\4326\\county.shp");
        ShapefileDataStore dataStore = new ShapefileDataStore(shapefile.toURI().toURL());
        SimpleFeatureSource featureSource = dataStore.getFeatureSource();

        // 创建地图内容
        MapContent map = new MapContent();
        map.setTitle("Shapefile with Bounding Box");

        // 为shapefile的特征创建样式
        Style style = SLD.createSimpleStyle(featureSource.getSchema());
        Layer layer = new FeatureLayer(featureSource, style);
        map.addLayer(layer);

        // 计算边界框
        ReferencedEnvelope bounds = featureSource.getBounds();
        GeometryFactory geometryFactory = new GeometryFactory();
        Polygon boundingBox = (Polygon) geometryFactory.toGeometry(bounds);

        // 为边界框创建特征类型
        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
        typeBuilder.setName("BoundingBoxFeature");
        typeBuilder.setCRS(featureSource.getSchema().getCoordinateReferenceSystem());
        typeBuilder.add("geometry", Polygon.class);
        SimpleFeatureType boundingBoxType = typeBuilder.buildFeatureType();

        // 创建存储边界框特征的列表
        List<SimpleFeature> boundingBoxFeatures = new ArrayList<>();

        // 创建带有边界框几何的特征
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(boundingBoxType);
        featureBuilder.add(boundingBox);
        SimpleFeature boundingBoxFeature = featureBuilder.buildFeature("BoundingBoxFeature");
        boundingBoxFeatures.add(boundingBoxFeature);

        //  为边界框创建特征集合
        SimpleFeatureCollection boundingBoxFeatureCollection = DataUtilities.collection(boundingBoxFeatures);
        SimpleFeatureSource boundingBoxFeatureSource = DataUtilities.source(boundingBoxFeatureCollection);

        // 为边界框创建样式
        Style boundingBoxStyle = SLD.createPolygonStyle(Color.RED, null, 1.0f);
        Layer boundingBoxLayer = new FeatureLayer(boundingBoxFeatureSource, boundingBoxStyle);
        map.addLayer(boundingBoxLayer);

//        ReferencedEnvelope mapArea = featureSource.getBounds();

        // 计算新的边界(缩小图形)
        ReferencedEnvelope originalBounds = featureSource.getBounds();
        Coordinate center = originalBounds.centre();
        double scaleFactor = 1.5;
        double newWidth = originalBounds.getWidth() * scaleFactor; // scaleFactor > 1
        double newHeight = originalBounds.getHeight() * scaleFactor; // scaleFactor > 1
        ReferencedEnvelope newBounds = new ReferencedEnvelope(
                center.x - newWidth / 2, center.x + newWidth / 2,
                center.y - newHeight / 2, center.y + newHeight / 2,
                originalBounds.getCoordinateReferenceSystem()
        );

        // 渲染地图
        StreamingRenderer renderer = new StreamingRenderer();
        renderer.setMapContent(map);
        int imageWidth = 800;
        int imageHeight = 600;
        BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = image.createGraphics();

        // 设置背景色为透明
        graphics.setComposite(AlphaComposite.Clear);
        graphics.fillRect(0, 0, imageWidth, imageHeight);
        graphics.setComposite(AlphaComposite.SrcOver);

        // 创建红色字体
        Font chineseFont = new Font("宋体", Font.PLAIN, 14);
        graphics.setFont(chineseFont);
        graphics.setColor(Color.RED);

        // 获取Polygon的顶点坐标
        Coordinate[] coordinates = boundingBox.getCoordinates();

        // 计算最小外接矩形的坐标
        double minX = Double.POSITIVE_INFINITY;
        double minY = Double.POSITIVE_INFINITY;
        double maxX = Double.NEGATIVE_INFINITY;
        double maxY = Double.NEGATIVE_INFINITY;

        for (Coordinate coordinate : coordinates) {
            minX = Math.min(minX, coordinate.x);
            minY = Math.min(minY, coordinate.y);
            maxX = Math.max(maxX, coordinate.x);
            maxY = Math.max(maxY, coordinate.y);
        }

        // 在左上角显示最小外接矩形的顶底坐标
        String topLeftTextLng = "左上角:" + minX;
        graphics.drawString(topLeftTextLng, 10, 20);
        String topLeftTextLat = maxY + "";
        graphics.drawString(topLeftTextLat, 10, 40);

        // 在右上角显示最小外接矩形的顶底坐标
        String topRightTextLng = "右上角:" + maxX;
        int textWidthLng = graphics.getFontMetrics().stringWidth(topRightTextLng);
        graphics.drawString(topRightTextLng, imageWidth - textWidthLng - 10, 20);
        String topRightTextLat = maxY + "";
        int textWidthLat = graphics.getFontMetrics().stringWidth(topRightTextLng);
        graphics.drawString(topRightTextLat, imageWidth - textWidthLat - 10, 40);

        // 在左下角显示最小外接矩形的顶底坐标
        String bottomLeftTextLng = "左下角:" + minX;
        graphics.drawString(bottomLeftTextLng, 10, imageHeight - 30);
        String bottomLeftTextLat = minY + "";
        graphics.drawString(bottomLeftTextLat, 10, imageHeight - 10);

        // 在右下角显示最小外接矩形的顶底坐标
        String bottomRightTextLng = "右下角:" + maxX;
        graphics.drawString(bottomRightTextLng, imageWidth - textWidthLng - 10, imageHeight - 30);
        String bottomRightTextLat = minY + "";
        graphics.drawString(bottomRightTextLat, imageWidth - textWidthLat - 10, imageHeight - 10);

        // 渲染地图到图像
        Rectangle imageBounds = new Rectangle(0, 0, imageWidth, imageHeight);
        renderer.paint(graphics, imageBounds, newBounds);
        // 保存图像到文件
        File pngFile = new File("E:\\code\\gitee\\gis-server\\data\\output\\photo\\map_view.png");
        ImageIO.write(image, "png", pngFile);

        //  输出文件路径
        System.out.println("Output file: " + pngFile.getAbsolutePath());

        // 清理资源
        graphics.dispose();
//        map.dispose();

        // 显示地图
        JMapFrame.showMap(map);
    }

    public static void getFourScreenshots(Layer layer, String outputPath) throws IOException {
        // 创建地图内容
        MapContent map = new MapContent();
        map.setTitle("Shapefile with Bounding Box");

        FeatureSource<?, ?> featureSource = layer.getFeatureSource();
        map.addLayer(layer);

        // 计算边界框
        ReferencedEnvelope bounds = featureSource.getBounds();
        GeometryFactory geometryFactory = new GeometryFactory();
        Polygon boundingBox = (Polygon) geometryFactory.toGeometry(bounds);

        // 为边界框创建特征类型
        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
        typeBuilder.setName("BoundingBoxFeature");
        typeBuilder.setCRS(featureSource.getSchema().getCoordinateReferenceSystem());
        typeBuilder.add("geometry", Polygon.class);
        SimpleFeatureType boundingBoxType = typeBuilder.buildFeatureType();

        // 创建存储边界框特征的列表
        List<SimpleFeature> boundingBoxFeatures = new ArrayList<>();

        // 创建带有边界框几何的特征
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(boundingBoxType);
        featureBuilder.add(boundingBox);
        SimpleFeature boundingBoxFeature = featureBuilder.buildFeature("BoundingBoxFeature");
        boundingBoxFeatures.add(boundingBoxFeature);

        //  为边界框创建特征集合
        SimpleFeatureCollection boundingBoxFeatureCollection = DataUtilities.collection(boundingBoxFeatures);
        SimpleFeatureSource boundingBoxFeatureSource = DataUtilities.source(boundingBoxFeatureCollection);

        // 为边界框创建样式
        Style boundingBoxStyle = SLD.createPolygonStyle(Color.RED, null, 2.0f);
        Layer boundingBoxLayer = new FeatureLayer(boundingBoxFeatureSource, boundingBoxStyle);
        map.addLayer(boundingBoxLayer);

//        ReferencedEnvelope mapArea = featureSource.getBounds();

        // 计算新的边界(缩小图形)
        ReferencedEnvelope originalBounds = featureSource.getBounds();
        Coordinate center = originalBounds.centre();
        double scaleFactor = 1.5;
        double newWidth = originalBounds.getWidth() * scaleFactor; // scaleFactor > 1
        double newHeight = originalBounds.getHeight() * scaleFactor; // scaleFactor > 1
        ReferencedEnvelope newBounds = new ReferencedEnvelope(
                center.x - newWidth / 2, center.x + newWidth / 2,
                center.y - newHeight / 2, center.y + newHeight / 2,
                originalBounds.getCoordinateReferenceSystem()
        );

        // 渲染地图
        StreamingRenderer renderer = new StreamingRenderer();
        renderer.setMapContent(map);
        int imageWidth = 800;
        int imageHeight = 600;
        BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = image.createGraphics();

        // 设置背景色为透明
        graphics.setComposite(AlphaComposite.Clear);
        graphics.fillRect(0, 0, imageWidth, imageHeight);
        graphics.setComposite(AlphaComposite.SrcOver);

        // 创建红色字体
        Font chineseFont = new Font("宋体", Font.PLAIN, 14);
        graphics.setFont(chineseFont);
        graphics.setColor(Color.RED);

        // 获取Polygon的顶点坐标
        Coordinate[] coordinates = boundingBox.getCoordinates();

        // 计算最小外接矩形的坐标
        double minX = Double.POSITIVE_INFINITY;
        double minY = Double.POSITIVE_INFINITY;
        double maxX = Double.NEGATIVE_INFINITY;
        double maxY = Double.NEGATIVE_INFINITY;

        for (Coordinate coordinate : coordinates) {
            minX = Math.min(minX, coordinate.x);
            minY = Math.min(minY, coordinate.y);
            maxX = Math.max(maxX, coordinate.x);
            maxY = Math.max(maxY, coordinate.y);
        }

        // 在左上角显示最小外接矩形的顶底坐标
        String topLeftTextLng = "西北角:" + minX;
        graphics.drawString(topLeftTextLng, 10, 40);
        String topLeftTextLat = maxY + "";
        graphics.drawString(topLeftTextLat, 10, 60);

        // 在右上角显示最小外接矩形的顶底坐标
        String topRightTextLng = "东北角:" + maxX;
        int textWidthLng = graphics.getFontMetrics().stringWidth(topRightTextLng);
        graphics.drawString(topRightTextLng, imageWidth - textWidthLng - 10, 40);
        String topRightTextLat = maxY + "";
        int textWidthLat = graphics.getFontMetrics().stringWidth(topRightTextLng);
        graphics.drawString(topRightTextLat, imageWidth - textWidthLat - 10, 60);

        // 在左下角显示最小外接矩形的顶底坐标
        String bottomLeftTextLng = "西南角:" + minX;
        graphics.drawString(bottomLeftTextLng, 10, imageHeight - 50);
        String bottomLeftTextLat = minY + "";
        graphics.drawString(bottomLeftTextLat, 10, imageHeight - 30);

        // 在右下角显示最小外接矩形的顶底坐标
        String bottomRightTextLng = "东南角:" + maxX;
        graphics.drawString(bottomRightTextLng, imageWidth - textWidthLng - 10, imageHeight - 50);
        String bottomRightTextLat = minY + "";
        graphics.drawString(bottomRightTextLat, imageWidth - textWidthLat - 10, imageHeight - 30);

        graphics.drawString("地块编号：3201050040021719739542102",imageWidth/2-150,imageHeight - 30);

        // 渲染地图到图像
        Rectangle imageBounds = new Rectangle(0, 0, imageWidth, imageHeight);
        renderer.paint(graphics, imageBounds, newBounds);
        // 保存图像到文件
        File pngFile = new File(outputPath);
        ImageIO.write(image, "png", pngFile);

        //  输出文件路径
        System.out.println("Output file: " + pngFile.getAbsolutePath());

        // 清理资源
        graphics.dispose();
        map.dispose();
    }

    public static Style createCustomStyle() {
        StyleBuilder sb = new StyleBuilder();

        // 设置边框样式。如果不需要边框，可以设置为null或适当的样式
        Stroke stroke = sb.createStroke(Color.BLUE, 0.5);

        // 设置填充样式，颜色为蓝色，透明度为30%
        Fill fill = sb.createFill(Color.BLUE, 0.3);

        // 创建并返回多边形样式
        return sb.createStyle(sb.createPolygonSymbolizer(stroke, fill, "the_geom"));
    }

    public static void getFourScreenshots1(Layer layer, String outputPath) throws IOException {
        // 创建地图内容
        MapContent map = new MapContent();
        map.setTitle("Shapefile with Bounding Box");

        FeatureSource<?, ?> featureSource = layer.getFeatureSource();
        map.addLayer(layer);

        // 计算边界框
        ReferencedEnvelope bounds = featureSource.getBounds();
        GeometryFactory geometryFactory = new GeometryFactory();
        Polygon boundingBox = (Polygon) geometryFactory.toGeometry(bounds);

        // 为边界框创建特征类型
        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
        typeBuilder.setName("BoundingBoxFeature");
        typeBuilder.setCRS(featureSource.getSchema().getCoordinateReferenceSystem());
        typeBuilder.add("geometry", Polygon.class);
        SimpleFeatureType boundingBoxType = typeBuilder.buildFeatureType();

        // 创建存储边界框特征的列表
        List<SimpleFeature> boundingBoxFeatures = new ArrayList<>();
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(boundingBoxType);
        featureBuilder.add(boundingBox);
        SimpleFeature boundingBoxFeature = featureBuilder.buildFeature("BoundingBoxFeature");
        boundingBoxFeatures.add(boundingBoxFeature);

        // 为边界框创建特征集合
        SimpleFeatureCollection boundingBoxFeatureCollection = DataUtilities.collection(boundingBoxFeatures);
        SimpleFeatureSource boundingBoxFeatureSource = DataUtilities.source(boundingBoxFeatureCollection);

        // 为边界框创建样式
        Style boundingBoxStyle = SLD.createPolygonStyle(Color.RED, null, 1.0f);
        Layer boundingBoxLayer = new FeatureLayer(boundingBoxFeatureSource, boundingBoxStyle);
        map.addLayer(boundingBoxLayer);

        // 计算新的边界(缩小图形)
        ReferencedEnvelope originalBounds = featureSource.getBounds();
        Coordinate center = originalBounds.centre();
        double scaleFactor = 1.5;
        double newWidth = originalBounds.getWidth() * scaleFactor;
        double newHeight = originalBounds.getHeight() * scaleFactor;
        ReferencedEnvelope newBounds = new ReferencedEnvelope(
                center.x - newWidth / 2, center.x + newWidth / 2,
                center.y - newHeight / 2, center.y + newHeight / 2,
                originalBounds.getCoordinateReferenceSystem()
        );

        // 渲染地图
        StreamingRenderer renderer = new StreamingRenderer();
        renderer.setMapContent(map);
        int imageWidth = 800;
        int imageHeight = 600;
        BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = image.createGraphics();

        // 设置背景色为透明
        graphics.setComposite(AlphaComposite.Clear);
        graphics.fillRect(0, 0, imageWidth, imageHeight);
        graphics.setComposite(AlphaComposite.SrcOver);

        // 创建红色字体
        Font chineseFont = new Font("宋体", Font.PLAIN, 14);
        graphics.setFont(chineseFont);
        graphics.setColor(Color.RED);

        // 获取Polygon的顶点坐标
        Coordinate[] coordinates = boundingBox.getCoordinates();

        // 计算最小外接矩形的四个顶点坐标
        Coordinate topLeft = new Coordinate(bounds.getMinX(), bounds.getMaxY());
        Coordinate topRight = new Coordinate(bounds.getMaxX(), bounds.getMaxY());
        Coordinate bottomLeft = new Coordinate(bounds.getMinX(), bounds.getMinY());
        Coordinate bottomRight = new Coordinate(bounds.getMaxX(), bounds.getMinY());

        // 在左上角显示最小外接矩形的顶点坐标
        String topLeftTextLng = "左上角: " + topLeft.x;
        graphics.drawString(topLeftTextLng, 10, 20);
        String topLeftTextLat = String.valueOf(topLeft.y);
        graphics.drawString(topLeftTextLat, 10, 40);

        // 在右上角显示最小外接矩形的顶点坐标
        String topRightTextLng = "右上角: " + topRight.x;
        int textWidthLng = graphics.getFontMetrics().stringWidth(topRightTextLng);
        graphics.drawString(topRightTextLng, imageWidth - textWidthLng - 10, 20);
        String topRightTextLat = String.valueOf(topRight.y);
        int textWidthLat = graphics.getFontMetrics().stringWidth(topRightTextLat);
        graphics.drawString(topRightTextLat, imageWidth - textWidthLat - 10, 40);

        // 在左下角显示最小外接矩形的顶点坐标
        String bottomLeftTextLng = "左下角: " + bottomLeft.x;
        graphics.drawString(bottomLeftTextLng, 10, imageHeight - 30);
        String bottomLeftTextLat = String.valueOf(bottomLeft.y);
        graphics.drawString(bottomLeftTextLat, 10, imageHeight - 10);

        // 在右下角显示最小外接矩形的顶点坐标
        String bottomRightTextLng = "右下角: " + bottomRight.x;
        graphics.drawString(bottomRightTextLng, imageWidth - textWidthLng - 10, imageHeight - 30);
        String bottomRightTextLat = String.valueOf(bottomRight.y);
        graphics.drawString(bottomRightTextLat, imageWidth - textWidthLat - 10, imageHeight - 10);

        // 渲染地图到图像
        Rectangle imageBounds = new Rectangle(0, 0, imageWidth, imageHeight);
        renderer.paint(graphics, imageBounds, newBounds);

        // 保存图像到文件
        File pngFile = new File(outputPath);
        ImageIO.write(image, "png", pngFile);

        // 输出文件路径
        System.out.println("Output file: " + pngFile.getAbsolutePath());

        // 清理资源
        graphics.dispose();
        map.dispose();
    }
}
